﻿using Abp.AspNetCore;
using Abp.AspNetCore.Configuration;
using Abp.AspNetCore.SignalR;
using Abp.Configuration.Startup;
using Abp.Hangfire;
using Abp.Modules;
using Abp.Reflection.Extensions;
using Abp.Runtime.Caching.Redis;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using Mt.Site.Application;
using Mt.Site.Core.Authentication.TwoFactor;
using Mt.Site.Core.Base.Navigation;
using Mt.Site.Core.Base.Utils.FileIO;
using Mt.Site.Core.BundlerMinifier;
using Mt.Site.Core.Configuration;
using Mt.Site.EntityFrameworkCore;
using Mt.Site.Web.Authentication.JwtBearer;
using Mt.Site.Web.Configuration;
using Mt.Site.Web.Scripting;
using System.IO;
using System.Text;

namespace Mt.Site.Web
{
    [DependsOn(
        typeof(MtSiteApplicationModule),
        typeof(MtSiteEfModule),
        typeof(AbpAspNetCoreSignalRModule),
        typeof(AbpAspNetCoreModule),
        typeof(AbpRedisCacheModule), //AbpRedisCacheModule dependency (and Abp.RedisCache nuget package) can be removed if not using Redis cache
        typeof(AbpHangfireAspNetCoreModule) //AbpHangfireModule dependency (and Abp.Hangfire.AspNetCore nuget package) can be removed if not using Hangfire
    )]
    public class MtSiteWebCoreModule : AbpModule
    {
        private readonly IWebHostEnvironment _env;
        private readonly IConfigurationRoot _appConfiguration;

        public MtSiteWebCoreModule(IWebHostEnvironment env)
        {
            _env = env;
            _appConfiguration = env.GetAppConfiguration();
        }

        public override void PreInitialize()
        {
            //Configuration.Modules.AbpWebCommon().ApiProxyScripting.RemoveAsyncPostfixOnProxyGeneration = false;
            //Configuration.Modules.AbpWebCommon().MultiTenancy.DomainFormat = _appConfiguration["App:ServerRootAddress"];

            //Set default connection string
            Configuration.DefaultNameOrConnectionString = _appConfiguration.GetConnectionStringByAutoDecrypt(
                MtSiteConsts2.ConnectionStringName
                );

            Configuration.Modules.AbpAspNetCore()
                 .CreateControllersForAppServices(typeof(MtSiteApplicationBaseModule).GetAssembly(), "app", true)
                 .Where(type => typeof(IBackEndAppService).IsAssignableFrom(type));
            Configuration.Modules.AbpAspNetCore()
                 .CreateControllersForAppServices(typeof(MtSiteApplicationBaseModule).GetAssembly(), "front", true)
                 .Where(type => typeof(IFrontEndAppService).IsAssignableFrom(type));
            Configuration.Modules.AbpAspNetCore()
                 .CreateControllersForAppServices(typeof(MtSiteApplicationModule).GetAssembly(), "app", true)
                 .Where(type => typeof(IBackEndAppService).IsAssignableFrom(type));
            Configuration.Modules.AbpAspNetCore()
                 .CreateControllersForAppServices(typeof(MtSiteApplicationModule).GetAssembly(), "front", true)
                 .Where(type => typeof(IFrontEndAppService).IsAssignableFrom(type));

            Configuration.Caching.Configure(TwoFactorCodeCacheItem.CacheName, cache =>
            {
                cache.DefaultSlidingExpireTime = TwoFactorCodeCacheItem.DefaultSlidingExpireTime;
            });

            if (_appConfiguration["Authentication:JwtBearer:IsEnabled"] != null 
                && bool.Parse(_appConfiguration["Authentication:JwtBearer:IsEnabled"]))
            {
                ConfigureTokenAuth();
            }

            Configuration.ReplaceService<IAppConfigurationAccessor, AppConfigurationAccessor>();
            Configuration.ReplaceService<IAppConfigurationWriter, AppConfigurationWriter>();

            Configuration.Modules.AbpWebCommon().ApiProxyScripting.Generators[AngularProxyScriptGenerator.Name] = typeof(AngularProxyScriptGenerator);
        }

        private void ConfigureTokenAuth()
        {
            IocManager.Register<TokenAuthConfiguration>();
            var tokenAuthConfig = IocManager.Resolve<TokenAuthConfiguration>();

            tokenAuthConfig.SecurityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_appConfiguration["Authentication:JwtBearer:SecurityKey"]));
            tokenAuthConfig.Issuer = _appConfiguration["Authentication:JwtBearer:Issuer"];
            tokenAuthConfig.Audience = _appConfiguration["Authentication:JwtBearer:Audience"];
            tokenAuthConfig.SigningCredentials = new SigningCredentials(tokenAuthConfig.SecurityKey, SecurityAlgorithms.HmacSha256);
            // token有效期
            tokenAuthConfig.AccessTokenExpiration = AppConsts.AccessTokenExpiration;
            tokenAuthConfig.RefreshTokenExpiration = AppConsts.RefreshTokenExpiration;
        }

        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(typeof(MtSiteWebCoreModule).GetAssembly());
        }

        public override void PostInitialize()
        {
            SetAppFolders();

            //加载栏目、路由缓存（都是单例模式，不需要回收）, 21.5.26 内容栏目改为懒加载
            IocManager.Resolve<MtNavigationManager>().LoadSystemMenus();

            IocManager.Resolve<IBundlerHelper>().ProcessStaticBundle(false);
        }

        private void SetAppFolders()
        {
            var appFolders = IocManager.Resolve<AppFolders>();

            var webLogsFolder_Relative = $"App_Data{Path.DirectorySeparatorChar}Logs";
            var configs_Relative = $"App_Data{Path.DirectorySeparatorChar}Configs";
            appFolders.StaticPageFolder_Relative = $"content{Path.DirectorySeparatorChar}Caches";

            var sampleProfileImagesFolder_Relative = $"content{Path.DirectorySeparatorChar}mt{Path.DirectorySeparatorChar}images{Path.DirectorySeparatorChar}SampleProfilePics";
            appFolders.TempFileDownloadFolder_Relative = $"mtsc{Path.DirectorySeparatorChar}Temp{Path.DirectorySeparatorChar}Downloads";
            appFolders.TempFileFolder_Relative = $"mtsc{Path.DirectorySeparatorChar}Temp{Path.DirectorySeparatorChar}Files";
            appFolders.UploadFilesFolder_Relative = $"mtsc{Path.DirectorySeparatorChar}uploads";
            appFolders.TempFolder_Relative = $"mtsc{Path.DirectorySeparatorChar}Temp";
            appFolders.RootFolder_Relative = "mtsc";

            appFolders.SampleProfileImagesFolder = Path.Combine(_env.WebRootPath, sampleProfileImagesFolder_Relative);
            appFolders.TempFileDownloadFolder = Path.Combine(_env.WebRootPath, appFolders.TempFileDownloadFolder_Relative);
            appFolders.TempFileFolder = Path.Combine(_env.WebRootPath, appFolders.TempFileFolder_Relative);
            appFolders.UploadFilesFolder = Path.Combine(_env.WebRootPath, appFolders.UploadFilesFolder_Relative);
            appFolders.TempFolder = Path.Combine(_env.WebRootPath, appFolders.TempFolder_Relative);
            appFolders.RootFolder = Path.Combine(_env.WebRootPath, appFolders.RootFolder_Relative);

            appFolders.WebLogsFolder = Path.Combine(_env.ContentRootPath, webLogsFolder_Relative);
            appFolders.Configs = Path.Combine(_env.ContentRootPath, configs_Relative);
            appFolders.StaticPageFolder = Path.Combine(_env.WebRootPath, appFolders.StaticPageFolder_Relative);
            try
            {
                FileHelper.FolderCreateIfNotExists(appFolders.TempFileDownloadFolder);
                FileHelper.FolderCreateIfNotExists(appFolders.TempFileFolder);
            }
            catch { }
        }
    }
}
